home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
dev
/
cross
/
GBDK-2.0.lha
/
GBDK
/
lib
/
div.s
< prev
next >
Wrap
Text File
|
1998-10-01
|
4KB
|
161 lines
.include "global.s"
.area _CODE
;; 16-bit division
;;
;; Entry conditions
;; BC = dividend
;; DE = divisor
;;
;; Exit conditions
;; BC = quotient
;; DE = remainder
;; If divisor is non-zero, carry=0
;; If divisor is 0, carry=1 and both quotient and remainder are 0
;;
;; Register used: AF,BC,DE,HL
.div16::
.mod16::
;; Determine sign of quotient by xor-ing high bytes of dividend
;; and divisor. Quotient is positive if signs are the same, negative
;; if signs are different
;; Remainder has same sign as dividend
LD A,B ; Get high byte of dividend
LD (.srem),A ; Save as sign of remainder
XOR D ; Xor with high byte of divisor
LD (.squot),A ; Save sign of quotient
;; Take absolute value of divisor
BIT 7,D
JP Z,.chkde ; Jump if divisor is positive
SUB A ; Substract divisor from 0
SUB E
LD E,A
SBC A ; Propagate borrow (A=0xFF if borrow)
SUB D
LD D,A
;; Take absolute value of dividend
.chkde:
BIT 7,B
JP Z,.dodiv ; Jump if dividend is positive
SUB A ; Substract dividend from 0
SUB C
LD C,A
SBC A ; Propagate borrow (A=0xFF if borrow)
SUB B
LD B,A
;; Divide absolute values
.dodiv:
CALL .divu16
RET C ; Exit if divide by zero
;; Negate quotient if it is negative
LD A,(.squot)
AND #0x80
JP Z,.dorem ; Jump if quotient is positive
SUB A ; Substract quotient from 0
SUB C
LD C,A
SBC A ; Propagate borrow (A=0xFF if borrow)
SUB B
LD B,A
.dorem:
;; Negate remainder if it is negative
LD A,(.srem)
AND #0x80
RET Z ; Return if remainder is positive
SUB A ; Substract remainder from 0
SUB E
LD E,A
SBC A ; Propagate remainder (A=0xFF if borrow)
SUB D
LD D,A
RET
.divu16::
.modu16::
;; Check for division by zero
LD A,E
OR D
JR NZ,.divide ; Branch if divisor is non-zero
LD BC,#0x00 ; Divide by zero error
LD D,B
LD E,C
SCF ; Set carry, invalid result
RET
.divide:
LD L,C ; L = low byte of dividend/quotient
LD H,B ; H = high byte of dividend/quotient
LD BC,#0x00 ; BC = remainder
OR A ; Clear carry to start
LD A,#16 ; 16 bits in dividend
.dvloop:
;; Shift next bit of quotient into bit 0 of dividend
;; Shift next MSB of dividend into LSB of remainder
;; BC holds both dividend and quotient. While we shift a bit from
;; MSB of dividend, we shift next bit of quotient in from carry
;; HL holds remainder
;; Do a 32-bit left shift, shifting carry to L, L to H,
;; H to C, C to B
LD (.dcnt),A
RL L ; Carry (next bit of quotient) to bit 0
RL H ; Shift remaining bytes
RL C
RL B ; Clears carry since BC was 0
;; If remainder is >= divisor, next bit of quotient is 1. This
;; bit goes to carry
PUSH BC ; Save current remainder
LD A,C ; Substract divisor from remainder
SBC E
LD C,A
LD A,B
SBC D
LD B,A
CCF ; Complement borrow so 1 indicates a
; successful substraction (this is the
; next bit of quotient)
JR C,.drop ; Jump if remainder is >= dividend
POP BC ; Otherwise, restore remainder
JR .nodrop
.drop:
INC SP
INC SP
.nodrop:
LD A,(.dcnt)
DEC A ; DEC does not affect carry flag
JR NZ,.dvloop
;; Shift last carry bit into quotient
LD D,B ; DE = remainder
LD E,C
RL L ; Carry to L
LD C,L ; C = low byte of quotient
RL H
LD B,H ; B = high byte of quotient
OR A ; Clear carry, valid result
RET
.div8::
.mod8::
LD A,C ; Sign extend
RLCA
SBC A
LD B,A
LD A,E ; Sign extend
RLCA
SBC A
LD D,A
JP .div16
.divu8::
.modu8::
LD B,#0x00
LD D,#0x00
JP .divu16
.area _BSS
.srem:
.ds 0x01 ; Sign of quotient
.squot:
.ds 0x01 ; Sign of remainder
.dcnt:
.ds 0x01 ; Counter for division